package com.dingdang.lock;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Objects;

/**
 * redis中命令都是原子性  abc
 * SETNX ： 如果redis中没有这个key，我们会将我们的key和value保存进去，并且返回true
 * 如果redis中有这个key，就什么都不做，直接返回false
 * <p>
 * getset：取旧赋新且保证原子性
 */
@Component
public class CurrentLock {

    @Autowired
    private RedisTemplate redisTemplate;

    //加锁方法
    public boolean lock(String key, String value) {
        if (redisTemplate.boundValueOps(key).setIfAbsent(value)) {//SETNX
            return true;
        }
        // 1   14.40    2   取出来1号线程的值 14.40  14.43   3 线程
        //避免锁超时而导致的死锁问题
        String oldValue = (String) redisTemplate.boundValueOps(key).get();
        if (StringUtils.isNoneBlank(oldValue) && Long.parseLong(oldValue) < new Date().getTime()) {
            //取旧赋新,原子性
            String oldValue2 = (String) redisTemplate.boundValueOps(key).getAndSet(value);
            //判断oldValue 与 oldValue2 是否一样
            if(Objects.equals(oldValue,oldValue2)){
                return true;
            }
        }
        return false;
    }


    //解锁方法
    public boolean unlock(String key, String value) {
        try {
            String oldValue = (String) redisTemplate.boundValueOps(key).get();
            if (Objects.equals(oldValue, value)) {
                redisTemplate.delete(key);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }
}
